﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using TheGameClient.Processes;
using TheGameClient.Webservices;
using Waaahsabi.Controls.TheGame;

namespace TheGameClient
{
	public partial class FeatureBankingControl : ISystemFeature
	{
		private List<BankAccount> _availableAccounts;
		private BankAccount _currentAccount;

		public FeatureBankingControl()
		{
			InitializeComponent();
			bankingControl.NewTransaction += BankingControlNewTransaction;
			bankingControl.AccountSelected += BankingControlAccountSelected;
			bankingControl.CheckReceiver += BankingControlCheckReceiver;
			ProcessId = Guid.NewGuid();
		}

		#region ISystemFeature Members

		public ulong InterfaceId
		{
			get { return new Guid("{F2DB69C0-1B0B-4734-8235-A145AF3590EF}").ToLong(); }
		}

		public Guid ProcessId { get; private set; }

		public string ProcessName
		{
			get { return "Banking"; }
		}

		public InterfaceCategory Category
		{
			get { return InterfaceCategory.SystemFeature; }
		}

		public ulong SystemId { get; private set; }

		public void Load(ulong systemId)
		{
			SystemId = systemId;
			App.Client.GetBankAccountCompleted += ClientGetBankAccountCompleted;
			App.Client.GetBankAccountAsync(App.InternalSessionId, SystemId);
		}

		#endregion

		private void ClientGetBankAccountCompleted(object sender, GetBankAccountCompletedEventArgs e)
		{
			App.Client.GetBankAccountCompleted -= ClientGetBankAccountCompleted;
			if (e.Error != null)
			{
				App.ServerError();
				return;
			}
			if (e.Result != null)
			{
				if (e.Result.Count == 1 && e.Result[0] != null)
					//means we have an account here, but we're not on a hacked connection
				{
					VisualStateManager.GoToState(bankingControl, "Normal", false);
					_currentAccount = e.Result[0];
					bankingControl.Balance = string.Format("{0:###,###,###,###,###,###.##}", _currentAccount.CachedAmount).Trim();
					bankingControl.MyBankAccountNumber =
						string.Format("{0:## ## ## ## ## ## ## ##}", _currentAccount.AccountNumber).Trim();
					App.Client.GetBankAccountMutationsCompleted += ClientGetBankAccountMutationsCompleted;
					App.Client.GetBankAccountMutationsAsync(App.InternalSessionId, SystemId, e.Result[0].AccountNumber);
				}
				else if (e.Result[0] == null) //we are on a hacked connection.
				{
					VisualStateManager.GoToState(bankingControl, "Hacked", false);
					_availableAccounts = e.Result.Where(it => it != null).ToList();
					_availableAccounts.ForEach(it => bankingControl.Accounts.Add(new BankControlAccount {Number = it.AccountNumber}));
					if (_currentAccount != null) //we're refreshing, so we take this account as the selected one
					{
						if (_availableAccounts.Where(it => it.Id == _currentAccount.Id).Count() == 1)
							//if this current account is still there (could've been deleted in the meantime)
						{
							App.Client.GetBankAccountMutationsCompleted += ClientGetBankAccountMutationsCompleted;
							App.Client.GetBankAccountMutationsAsync(App.InternalSessionId, SystemId, _currentAccount.AccountNumber);
						}
					}
				}
			}
			else
			{
				VisualStateManager.GoToState(bankingControl, "CreateAccount", false);
			}
		}

		private void ClientGetBankAccountMutationsCompleted(object sender, GetBankAccountMutationsCompletedEventArgs e)
		{
			App.Client.GetBankAccountMutationsCompleted -= ClientGetBankAccountMutationsCompleted;
			bankingControl.Mutations.Clear();
			if (e.Error != null)
			{
				App.ServerError();
				return;
			}
			if (e.Result != null)
			{
				e.Result.ForEach(it => bankingControl.Mutations.Add(
					new BankControlTransaction
					{
						Amount = it.Amount,
						Date = it.Date,
						Purpose = it.Purpose,
						TransactionPartner = it.TransactionPartnerAccountNumber + "@" + it.TransactionPartnerBankName
					}));

				//bankingControl.Mutations = new ObservableCollection<BankControlTransaction>(from x in e.Result select new BankControlTransaction
				//{
				//    Amount = x.Amount,
				//    Date = x.Date,
				//    Purpose = x.Purpose,
				//    TransactionPartner = x.TransactionPartnerAccountNumber + "@" + x.TransactionPartnerBankName
				//});
			}
		}

		private void BankingControlCheckReceiver(object sender, CheckReceiverEventArgs e)
		{
		}

		private void BankingControlAccountSelected(object sender, BankAccountSelectedEventArgs e)
		{
			_currentAccount = _availableAccounts.Where(it => it.AccountNumber == e.AccountNumber).First();
			bankingControl.Balance = string.Format("{0:000,000,000,000,000,000.00}", _currentAccount.CachedAmount);
			VisualStateManager.GoToState(bankingControl, "Normal", true);
			App.Client.GetBankAccountMutationsCompleted += ClientGetBankAccountMutationsCompleted;
			App.Client.GetBankAccountMutationsAsync(App.InternalSessionId, SystemId, e.AccountNumber);
		}

		private void BankingControlNewTransaction(object sender, NewTransactionEventArgs e)
		{
			App.Client.CreateTransactionCompleted += ClientCreateTransactionCompleted;
			App.Client.CreateTransactionAsync(App.InternalSessionId, SystemId, _currentAccount.AccountNumber,
			                                  e.TargetAccountNumber, e.TargetBankAddress, e.Amount, e.Purpose);
		}

		private void ClientCreateTransactionCompleted(object sender, CreateTransactionCompletedEventArgs e)
		{
			App.Client.CreateTransactionCompleted -= ClientCreateTransactionCompleted;
			if (e.Error != null)
			{
				App.ServerError();
				return;
			}
			if (e.Result)
			{
				App.Client.GetBankAccountMutationsCompleted += ClientGetBankAccountMutationsCompleted;
				App.Client.GetBankAccountMutationsAsync(App.InternalSessionId, SystemId, _currentAccount.AccountNumber);
				bankingControl.ResetFields();
				Load(SystemId); //refresh
			}
		}
	}

	public class FeatureBankingControlUiFactory : UiFactoryBase
	{
		public override InterfaceCategory UiCategory
		{
			get { return InterfaceCategory.SystemFeature; }
		}

		public override IProcess CreateProgram()
		{
			return new FeatureBankingControl();
		}
	}
}